﻿using System.Linq;
using Notoric.Commanding.CommandBase;

namespace Notoric.ViewModel
{
    /// <summary>
    /// An undoable command for removing a lyricist from a composition metadata.
    /// </summary>
    public class RemoveLyricistCommand : UndoableCommandBase
    {
        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="RemoveLyricistCommand"/> class.
        /// </summary>
        /// <param name="undoStack">The undo command stack</param>
        /// <param name="redoStack">The redo command stack</param>
        public RemoveLyricistCommand(CommandStack undoStack, CommandStack redoStack)
            : base(undoStack, redoStack)
        {
            AddParameter<Elements.Person>("Lyricist", ParameterDirection.In);

            Name = "Remove Lyricist";
        }

        #endregion

        #region Command Logic

        /// <inheritdoc/>
        protected override void CommandOperation(object parameter)
        {
            var modelPerson = Lyricist.AdaptedElement as Model.Elements.PersonElement;
            var modelComposition = modelPerson.FindOwner<Model.Elements.CompositionElement>();
            index = modelComposition.Lyricists.IndexOf(modelPerson);
            modelComposition.Lyricists.RemoveAt(index);

            Lyricist.FindOwner<Elements.Project>().IsModified = true;
        }

        /// <inheritdoc/>
        protected override void RedoOperation()
        {
            var modelPerson = Lyricist.AdaptedElement as Model.Elements.PersonElement;
            var modelComposition = modelPerson.FindOwner<Model.Elements.CompositionElement>();
            modelComposition.Lyricists.Remove(modelPerson);

            Lyricist.FindOwner<Elements.Project>().IsModified = true;
        }

        /// <inheritdoc/>
        protected override void UndoOperation()
        {
            var modelPerson = Lyricist.AdaptedElement as Model.Elements.PersonElement;
            var modelComposition = modelPerson.FindOwner<Model.Elements.CompositionElement>();
            modelComposition.Lyricists.Insert(index, modelPerson);
            var composition = Lyricist.FindOwner<Elements.Composition>();
            var vmLyricist = composition.Lyricists.First(c => c.AdaptedElement == Lyricist.AdaptedElement);
            composition.Lyricists[composition.Lyricists.IndexOf(vmLyricist)] = Lyricist;

            Lyricist.FindOwner<Elements.Project>().IsModified = true;
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets or sets the removed lyricist.
        /// </summary>
        /// <value>
        /// <para>
        /// Type: <see cref="Elements.Person"/>
        /// </para>
        /// <para>
        /// The lyricist to be removed by this command.<br/>
        /// This property wraps the "Lyricist" command parameter.
        /// </para>
        /// </value>
        public Elements.Person Lyricist
        {
            get { return GetParameterValue<Elements.Person>("Lyricist"); }
            set { SetParameterValue<Elements.Person>("Lyricist", value); }
        }

        #endregion

        #region Private Fields

        /// <summary>
        /// Holds the index of the removed lyricist.
        /// </summary>
        private int index;

        #endregion
    }
}
